package org.zdc.pivot.wtk;
import haxe.Json;
import nme.display.Graphics;
import nme.display.Sprite;
import nme.events.TimerEvent;
import nme.utils.Timer;
import org.zdc.core.IllegalArgumentException;
import org.zdc.core.Util;
import org.zdc.pivot.wtk.listener.IComponentListener;
import org.zdc.pivot.wtk.listener.IComponentStateListener;
import org.zdc.pivot.wtk.listener.IComponentMouseListener;
import org.zdc.pivot.wtk.listener.IComponentMouseButtonListener;
import org.zdc.pivot.wtk.listener.IComponentMouseWheelListener;
import org.zdc.pivot.wtk.listener.IComponentKeyListener;
import org.zdc.pivot.wtk.listener.IComponentTooltipListener;
import org.zdc.pivot.wtk.listener.IComponentClassListener;
import org.zdc.pivot.wtk.listener.IComponentDecoratorListener;
import org.zdc.pivot.wtk.listener.IComponentDataListener;
import org.zdc.pivot.wtk.listener.IComponentStyleListener;
import org.zdc.pivot.wtk.listener.ListenerList;
import org.zdc.pivot.wtk.listener.WTKListenerList;
import org.zdc.pivot.wtk.skin.ISkin;
import nme.ObjectHash;
using StringTools;

class Component extends Sprite,
				implements IConstrainedVisual
{
	//皮肤
	private var skin:ISkin;
	
	//首选宽高
	private var preferredWidth:Float;
	private var preferredHeight:Float;
	
	//首先尺寸的边界
	private var minWidth:Float;
	private var maxWidth:Float;
	private var minHeight:Float;
	private var maxHeight:Float;
	
	//首选尺寸
	private var preferredSize:Dimensions; 
	
	//基线
	private var baseline:Float;
	
	//组件父容器
	private var cparent:Container;
	
	/**
	 * 已集成属性：
	 * parent
	 * x
	 * y
	 * visible
	 * name
	 */
	
	//装饰器
	private var decorators:Array<IDecorator>;
	private var decoratorSequence:Dynamic;
	 
	//组件的布局有效性(layout-valid)状态
	private var valid:Bool;
	
	//组件是否可用
	private var enabled:Bool;
	
	//鼠标位置
	private var mouseLocation:Point;
	
	//--------------------------------------------------------组件上面的光标
	private var cursor:Cursor;
	
	//--------------------------------------------------------提示框文本，延迟，及触发回调
	private var tooltipText:String;
	private var tooltipDelay:Int;
	private var triggerTooltipCallback:Timer;
	
	//拖拽源
	private var dragSource:IDragSource;
	
	//释下对象，覆盖sprite
	private var cDropTarget:IDropTarget;
	
	//--------------------------------------------------------菜单处理器
	private var menuHandler:IMenuHandler;
	
	//组件的样式
	private var styles:Dynamic;
	private var styleDictionary:Hash<Dynamic>;
	
	//用户数据
	private var userData:Hash<Dynamic>;
	private var userDataDictionary:Hash<Dynamic>;
	
	//容器的属性
	private var attributes:Hash<Dynamic>;
	
	//自动ID
	private var automationID:String = null;
	
	//事件侦听器对象列表
	private var componentListeners:ComponentListenerList;
	private var componentStateListeners:ComponentStateListenerList;
    private var componentDecoratorListeners:ComponentDecoratorListenerList;
    private var componentStyleListeners:ComponentStyleListenerList;
    private var componentMouseListeners:ComponentMouseListenerList;
    private var componentMouseButtonListeners:ComponentMouseButtonListenerList;
    private var componentMouseWheelListeners:ComponentMouseWheelListenerList;
    private var componentKeyListeners:ComponentKeyListenerList;
    private var componentTooltipListeners:ComponentTooltipListenerList;
    private var componentDataListeners:ComponentDataListenerList;
	
	//当前具有焦点的组件
	private static var focusedComponent:Component;
	
	//类型样式及命名样式
	private static var typedStyles:nme.ObjectHash < Class<Component>, Hash<Dynamic> >;
	private static var namedStyles:Hash<Hash<Dynamic>>;
	
	//类事件侦听器
	private static var componentClassListeners:ComponentClassListenerList;
	
	public function new() 
	{
		skin = null;
	
		//首选宽高
		preferredWidth = -1;
		preferredHeight = -1;

		//首先尺寸的边界
		minWidth = 0;
		maxWidth = Math.POSITIVE_INFINITY;
		minHeight = 0;
		maxHeight = Math.POSITIVE_INFINITY;

		//首选尺寸
		preferredSize = null; 

		//基线
		baseline = -1;
		valid = false;

		styleDictionary = new Hash<Dynamic>();
		componentListeners = new ComponentListenerList();
		componentStateListeners = new ComponentStateListenerList();
		componentDecoratorListeners = new ComponentDecoratorListenerList();
		componentStyleListeners = new ComponentStyleListenerList();
		componentMouseListeners = new ComponentMouseListenerList();
		componentMouseButtonListeners = new ComponentMouseButtonListenerList();
		componentMouseWheelListeners = new ComponentMouseWheelListenerList();
		componentKeyListeners = new ComponentKeyListenerList();
		componentTooltipListeners = new ComponentTooltipListenerList();
		componentDataListeners = new ComponentDataListenerList();
		typedStyles = new nme.ObjectHash < Class<Component>, Hash<Dynamic> > ();
		namedStyles = new Hash<Hash<Dynamic>>();
		
		super();
	}
	
	/**
	 * 绘制
	 */
	public function paint():Void {
		
	}
	
	/**
	 * 获取自动ID
	 * @return
	 */
	public function getAutomationID():String {
		return automationID;
	}
	
	/**
	 * 设置组件的自动ID， 这个值可以在组件被绑定到组件层级时，通过Automation.get获取组件的引用
	 * @param	id
	 */
	public function setAutomationID(id:String):Void {
		var prevID = automationID;
		this.automationID = id;
		
		if (getDisplay() != null) {
			if (prevID != null) {
				Automation.remove(prevID);
			}
			
			if (id != null) {
				Automation.add(id, this);
			}
		}
	}
	
	/**
	 * 获取已经安装的皮肤
	 * @return
	 */
	public function getSkin():ISkin {
		return skin;
	}
	
	/**
	 * 设置皮肤，将替换所有之前的皮肤
	 * @param	skin
	 */
	public function setSkin(skin:ISkin):Void {
		if (skin == null) {
			throw new IllegalArgumentException("skin is null");
		}
		
		if (this.skin != null) {
			throw new IllegalArgumentException("Skin is already installed.");
		}
		
		this.skin = skin;
		styles = { };
		//~~~好像有点多余的写法？skin绑定有component
		skin.install(this);
		
		//应用所有已定义的样式
		var styleTypes = new List<Class<Component>>();
		
		//遍历所有组件层级，由上往下（父类到子类）实现层叠样式
		var t:Class <Component> = Type.getClass(this); 
		var componentSuperClass:Class<Dynamic> = Type.getSuperClass(Component);
		while (t != componentSuperClass) {
			styleTypes.push(t);
			t = untyped Type.getSuperClass(t);
		}
		
		var styleType:Class<Component>;
		for (s in styleTypes) {
			styleType = s;
			var stylesLocal = typedStyles.get(styleType);
			if (stylesLocal != null) {
				setStyles(stylesLocal);
			}
		}
		
		invalidate();
		repaint();
	}
	
	/**
	 * 安装皮肤
	 * @param	componentClass
	 */
	public function installSkin(componentClass:Class<Component>):Void {
		var type = Type.getClass(this);
		
		var theme = Theme.getTheme();
		var skinClass = theme.getSkinClass(type);
		
		while (skinClass == null &&
			   type != componentClass && 
			   type != Component) {
			type = untyped Type.getSuperClass(type);
			
			if (type != Component) {
				skinClass = theme.getSkinClass(type);
			}
		}
		
		if (type == Component) {
			throw new IllegalArgumentException(Type.getClassName(componentClass)
                + " is not an ancestor of " + Type.getClassName(Type.getClass(this)));
		}
		
		if (skinClass == null) {
			throw new IllegalArgumentException("No skin mapping for "
                + Type.getClassName(componentClass) + " found.");
		}
		
		if (type == componentClass) {
			try {
				setSkin(Type.createInstance(skinClass, []));
			}
			catch (e:Dynamic) {
				throw e;
			}
		}
	}
	
	public function getParent():Container {
		return cparent;
	}
	
	public function setParent(parent:Container):Void {
		var prevParent = this.cparent;
		this.cparent = parent;
		if (prevParent != null) {
			prevParent.removeChild(this);
			
			parent.addChild(this);
		}
		
		if (cparent != null) {
			cparent.descendantAdded(this);
		}
		
		componentListeners.parentChanged(this, prevParent);
	}
	
	public function getWindow():Window {
		return untyped getAncestor(Window);
	}
	
	public function getDisplay():Display {
		return untyped getAncestor(Display);
	}
	
	public function getAncestor(ancestorType:Class<Container>):Container {
		var c:Component = this;
		
		//如果在while之前Std.is(c, ancestorType)，返回自己？？？ 
		//也许只有在获取window和display这样的类才会有意义吧
		while (c != null &&
			   !(Std.is(c, ancestorType))) {
			c = c.getParent();
		}
		
		return untyped c;
	}
	
	/**
	 * 获取宽
	 * @return
	 */
	public function getWidth():Float {
		return skin.getWidth();
	}
	
	/**
	 * 设置宽
	 * @param	width
	 */
	public function setWidth(width:Float):Void {
		setSize(width, getHeight());
	}
	
	/**
	 * 获取高
	 * @return
	 */
	public function getHeight():Float {
		return skin.getWidth();
	}
	
	/**
	 * 设置高
	 * @param	height
	 */
	public function setHeight(height:Float):Void {
		setSize(getWidth(), height);
	}
	
	/**
	 * 获取尺寸
	 * @return
	 */
	public function getSize():Dimensions {
		return new Dimensions(getWidth(), getHeight());
	}
	
	/**
	 * 设置尺寸
	 * @param	width
	 * @param	height
	 */
	public function setSize(width:Float, height:Float):Void {
		if (width < 0) {
            throw new IllegalArgumentException("width is negative.");
        }

        if (height < 0) {
            throw new IllegalArgumentException("height is negative.");
        }
		
		var prevWid:Float = getWidth();
		var prevHei:Float = getHeight();
		
		if (width != prevWid ||
			height != prevWid) {
			//组件尺寸更改（很可能是正在布局的时候），必须标识为invalid以在validate()被调用时确保布局向下传播
			invalidate();
			
			//重画组件之前占据的区域
			if (cparent != null) {
				cparent.repaint(getDecoratedBounds());
			}
			
			//设置skin的尺寸
			skin.setSize(width, height);
			
			//重画现在组件占据的区域
			if (cparent != null) {
				cparent.repaint(getDecoratedBounds());
			}
		}
	}
	
	/**
	 * 获取期望宽
	 * @param	height
	 * @return
	 */
	public function getPreferredWidth(height:Float):Float {
		var prefWidLocal:Float;
		
		if (this.preferredWidth == -1) {
			if (height == -1) {
				prefWidLocal = getPreferredSize().width;
			}
			else {
				if (preferredSize != null &&
					preferredSize.height == height) {
					prefWidLocal = preferredSize.width;
				}
				else {
					var widLimits:Limits = getWidthLimits();
					prefWidLocal = widLimits.constrain(skin.getPreferredWidth(height));
				}
			}
		}
		else {
			prefWidLocal = this.preferredWidth;
		}
		
		return prefWidLocal;
	}
	
	/**
	 * 设置期望宽
	 * @param	preferredWidth
	 */
	public function setPreferredWidth(preferredWidth:Float):Void {
		setPreferredSize(preferredWidth, preferredHeight);
	}
	
	/**
	 * 组件是否被明确设置期望宽
	 * @return
	 */
	public function isPreferredWidthSet():Bool {
		return (preferredWidth != -1);
	}
	
	/**
	 * 获取期望高
	 * @param	width
	 * @return
	 */
	public function getPreferredHeight(width:Float):Float {
		var preferredHeightLocal:Float;

        if (this.preferredHeight == -1) {
            if (width == -1) {
                preferredHeightLocal = getPreferredSize().height;
            } else {
                if (preferredSize != null
                    && preferredSize.width == width) {
                    preferredHeightLocal = preferredSize.height;
                } else {
                    var heightLimits:Limits = getHeightLimits();
                    preferredHeightLocal = heightLimits.constrain(skin.getPreferredHeight(width)); 
                }
            }
        } else {
            preferredHeightLocal = this.preferredHeight;
        }

        return preferredHeightLocal;
	}
	
	/**
	 * 设置期望高
	 * @param	preferredHeight
	 */
	public function setPreferredHeight(preferredHeight:Float):Void {
		setPreferredSize(preferredWidth, preferredHeight);
	}
	
	/**
	 * 组件是否被明确设置期望高
	 */
	public function isPreferredHeightSet():Bool {
        return (preferredHeight != -1);
    }
	
	/**
	 * 获取期望尺寸
	 * @return
	 */
	public function getPreferredSize():Dimensions {
		if (preferredSize == null) {
            var preferredSizeLocal:Dimensions;
            if (preferredWidth == -1
                && preferredHeight == -1) {
                preferredSizeLocal = skin.getPreferredSize();
            } else if (preferredWidth == -1) {
                preferredSizeLocal = new Dimensions(skin.getPreferredWidth(preferredHeight),
                    preferredHeight);
            } else if (preferredHeight == -1) {
                preferredSizeLocal = new Dimensions(preferredWidth,
                    skin.getPreferredHeight(preferredWidth));
            } else {
                preferredSizeLocal = new Dimensions(preferredWidth, preferredHeight);
            }

            var widthLimits:Limits = getWidthLimits();
            var heightLimits:Limits = getHeightLimits();

            var preferredWidthLocal:Float = widthLimits.constrain(preferredSizeLocal.width);
            var preferredHeightLocal:Float = heightLimits.constrain(preferredSizeLocal.height);

            if (preferredSizeLocal.width > preferredWidthLocal) {
                preferredHeightLocal = heightLimits.constrain(skin.getPreferredHeight(preferredWidthLocal));
            }

            if (preferredSizeLocal.height > preferredHeightLocal) {
                preferredWidthLocal = widthLimits.constrain(skin.getPreferredWidth(preferredHeightLocal));
            }

            this.preferredSize = new Dimensions(preferredWidthLocal, preferredHeightLocal);
        }

        return preferredSize;
	}
	
	/**
	 * 设置期望尺寸
	 * @param	width
	 * @param	height
	 * @return
	 */
	public function setPreferredSize(preferredWidth:Float, preferredHeight:Float):Void {
		if (preferredWidth < -1) {
            throw new IllegalArgumentException(preferredWidth
                + " is not a valid value for preferredWidth.");
        }

        if (preferredHeight < -1) {
            throw new IllegalArgumentException(preferredHeight
                + " is not a valid value for preferredHeight.");
        }
		
		var previousPreferredWidth:Float = this.preferredWidth;
        var previousPreferredHeight:Float = this.preferredHeight;
		
        if (previousPreferredWidth != preferredWidth
            || previousPreferredHeight != preferredHeight) {
            this.preferredWidth = preferredWidth;
            this.preferredHeight = preferredHeight;

            invalidate();

            componentListeners.preferredSizeChanged(this, previousPreferredWidth,
                previousPreferredHeight);
        }
	}
	
	/**
	 * 组件是否被明确指定期望尺寸
	 * @return
	 */
	public function isPreferredSizeSet():Bool {
		return (isPreferredHeightSet() && isPreferredWidthSet());
	}
	
	/**
	 * 获取组件最小宽
	 * @return
	 */
	public function getMinimumWidth():Float {
		return minWidth;
	}
	
	/**
	 * 设置组件最小宽
	 * @param	minimumWidth
	 */
	public function setMinimumWidth(minimumWidth:Float):Void {
		setWidthLimits(minimumWidth, getMaximumWidth());
	}
	
	/**
	 * 获取组件最大宽
	 * @return
	 */
	public function getMaximumWidth():Float {
		return maxWidth;
	}
	
	/**
	 * 设置组件最大宽
	 */
	public function setMaximumWidth(maximumWidth:Float):Void {
		setWidthLimits(getMinimumWidth(), maximumWidth);
	}
	
	/**
	 * 获取组件宽极限
	 * @return
	 */
	public function getWidthLimits():Limits {
		return new Limits(minWidth, maxWidth);
	}
	
	/**
	 * 设置组件极限宽
	 * @param	minimumWidth
	 * @param	maximumWidth
	 */
	public function setWidthLimits(minimumWidth:Float, maximumWidth:Float):Void {
		var previousMinimumWidth:Float = this.minWidth;
        var previousMaximumWidth:Float = this.maxWidth;

        if (previousMinimumWidth != minimumWidth
            || previousMaximumWidth != maximumWidth) {
            if (minimumWidth < 0) {
                throw new IllegalArgumentException("minimumWidth is negative.");
            }

            if (minimumWidth > maximumWidth) {
                throw new IllegalArgumentException("minimumWidth is greater than maximumWidth.");
            }

            this.minWidth = minimumWidth;
            this.maxWidth = maximumWidth;

            invalidate();

            componentListeners.widthLimitsChanged(this, previousMinimumWidth, previousMaximumWidth);
        }
	}
	
	/**
	 * 获取组件最小高
	 * @return
	 */
	public function getMinimumHeight():Float {
		return minHeight;
	}
	
	/**
	 * 设置组件最小高
	 * @param	minimumHeight
	 */
	public function setMinimumHeight(minimumHeight:Float):Void {
		setHeightLimits(minimumHeight, getMaximumWidth());
	}
	
	/**
	 * 获取组件最大高
	 * @return
	 */
	public function getMaximumHeight():Float {
		return maxHeight;
	}
	
	/**
	 * 设置组件最大高
	 */
	public function setMaximumHeight(maximumHeight:Float):Void {
		setHeightLimits(getMinimumHeight(), maximumHeight);
	}
	
	/**
	 * 获取高极限
	 * @return
	 */
	public function getHeightLimits():Limits {
		return new Limits(minHeight, maxHeight);
	}
	
	/**
	 * 设置组件高极限
	 * @param	minimumHeight
	 * @param	maximumHeight
	 */
	public function setHeightLimits(minimumHeight:Float, maximumHeight:Float):Void {
		var previousMinimumHeight:Float = this.minHeight;
        var previousMaximumHeight:Float = this.maxHeight;

        if (previousMinimumHeight != minimumHeight
            || previousMaximumHeight != maximumHeight) {
            if (minimumHeight < 0) {
                throw new IllegalArgumentException("minimumHeight is negative.");
            }

            if (minimumHeight > maximumHeight) {
                throw new IllegalArgumentException("minimumHeight is greater than maximumHeight.");
            }

            this.maxHeight = minimumHeight;
            this.maxHeight = maximumHeight;

            invalidate();

            componentListeners.heightLimitsChanged(this, previousMinimumHeight, previousMaximumHeight);
        }
	}
	
	/**
	 * 获取x坐标
	 * @return
	 */
	public function getX():Float {
		return x;
	}
	
	/**
	 * 设置y坐标
	 * @param	x
	 * @return
	 */
	public function setX(x:Float):Void {
		setLocation(x, getY());
	}
	
	/**
	 * 获取y坐标
	 * @return
	 */
	public function getY():Float {
		return y;
	}
	
	/**
	 * 设置y坐标
	 * @param	y
	 */
	public function setY(y:Float):Void {
		setLocation(getX(), y);
	}
	
	/**
	 * 获取位置
	 * @return
	 */
	public function getLocation():Point {
		return new Point(getX(), getY());
	}
	
	/**
	 * 设置位置
	 * @param	x
	 * @param	y
	 */
	public function setLocation(x:Float, y:Float):Void {
		var previousX:Float = this.x;
        var previousY:Float = this.y;

        if (previousX != x
            || previousY != y) {
            // Redraw the region formerly occupied by this component
            if (cparent != null) {
                cparent.repaint(getDecoratedBounds());
            }

            // Set the new coordinates
            this.x = x;
            this.y = y;

            // Redraw the region currently occupied by this component
            if (cparent != null) {
                cparent.repaint(getDecoratedBounds());
            }

            componentListeners.locationChanged(this, previousX, previousY);
        }
	}
	
	/**
	 * 获取基线
	 * @param	?width
	 * @param	?height
	 * @return
	 */
	public function getBaseline(?width:Int, ?height:Int):Float {
		if (baseline == -1) {
			baseline = skin.getBaseline(width, height);
		}
		
		return baseline;
	}
	
	/**
	 * 判断组件是否包含特定区域。此方法为非长方形的组件与鼠标的交互提供便利
	 * @param	x
	 * @param	y
	 * @return
	 */
	//public function contains(x:Float, y:Float):Bool {
		//throw "UnsupportedOperation";
	//}
	
	/**
	 * 是否可见
	 * @return
	 */
	public function isVisible():Bool {
		return visible;
	}
	
	/**
	 * 设置可见性
	 * @param	visible
	 */
	public function setVisible(visible:Bool):Void {
		if (this.visible != visible) {
			if (!visible) {
                if (isFocused()) {
                    clearFocus();
                }

                // Ensure that the mouse out event is processed
                if (isMouseOver()) {
                    mouseOut();
                }
            }

            // Redraw the region formerly occupied by this component
            if (cparent != null) {
                cparent.repaint(getDecoratedBounds());
            }

            this.visible = visible;

            // Redraw the region currently occupied by this component
            if (cparent != null) {
                cparent.repaint(getDecoratedBounds());
            }

            // Ensure the layout is valid
            if (visible
                && !valid) {
                validate();
            }

            // Invalidate the parent
            if (cparent != null) {
                cparent.invalidate();
            }

            componentListeners.visibleChanged(this);
		}
	}
	
	/**
	 * 获取组件装饰器序列
	 * @return
	 */
	public function getDecorators():Dynamic {
		return decoratorSequence;
	}
	
	/**
	 * 
	 * @param	ancestor
	 * @param	xArgument
	 * @param	yArgument
	 * @return
	 */
	public function mapPointToAncestor(ancestor:Container, xArgument:Float, yArgument:Float):Point {
		if (ancestor == null) {
            throw new IllegalArgumentException("ancestor is null");
        }

        var coordinates:Point = null;

        var component:Component = this;

        while (component != null
            && coordinates == null) {
            if (component == ancestor) {
                coordinates = new Point(xArgument, yArgument);
            } else {
                xArgument += component.x;
                yArgument += component.y;

                component = component.getParent();
            }
        }

        return coordinates;
	}
	
	/**
	 * 组件是否显示。所谓的显示，即所有祖先必须可见
	 * @return
	 */
	public function isShowing():Bool {
		var component:Component = this;

        while (component != null
            && component.isVisible()
            && !(Std.is(component, Display))) {
            component = component.getParent();
        }

        return (component != null
            && component.isVisible());
	}
	
	/**
	 * 获取装饰器的区域范围
	 * @return
	 */
	public function getDecoratedBounds():Bounds {
		var decoratedBounds:Bounds = new Bounds(0, 0, getWidth(), getHeight());
		
        for (decorator in decorators) {
            decoratedBounds = Bounds.fromRect(decoratedBounds.union(decorator.getBounds(this)));
        }

        return new Bounds(decoratedBounds.x + x, decoratedBounds.y + y,
            decoratedBounds.width, decoratedBounds.height);
	}
	
	/**
	 * 获取组件的可见区域
	 * @param	xArgument
	 * @param	yArgument
	 * @param	width
	 * @param	height
	 * @return
	 */
	public function getVisibleArea(xArgument:Float, yArgument:Float, width:Float, height:Float):Bounds {
		return null; 
	}
	
	/**
	 * 确保组件指定区域可见
	 * @param	xArgument
	 * @param	yArgument
	 * @param	width
	 * @param	height
	 */
	public function scrollAreaToVisible(xArgument:Float, yArgument:Float, width:Float, height:Float):Void {
		
	}
	
	/**
	 * 组件可用状态
	 * @return
	 */
	public function isValid():Bool {
		return valid;
	}
	
	/**
	 * 把组件层级标识为不可用，并且清楚所有保存的期望尺寸
	 */
	public function invalidate():Void {
		valid = false;
		
		preferredSize = null;
		baseline = -1;
		
		if (cparent != null) {
			cparent.invalidate();
		}
	}
	
	/**
	 * 通过调用skin的layout布局组件
	 */
	public function validate():Void {
		if (!valid
            && visible) {
            layout();
            valid = true;
        }
	}
	
	/**
	 * 布局组件
	 */
	public function layout():Void {
		skin.layout();
	}
	
	
	public function repaint(?area:Bounds = null, ?immediate:Bool = false):Void 
	{
		
	}
	
	/**
	 * 
	 * @return
	 */
	public function getGraphics():Graphics {
		return graphics;
	}
	
	/**
	 * 设置组件的可用状态。可用的组件可以相应用户的输入事件
	 * @param	enabled
	 */
	public function setsetEnabled(enabled:Bool):Void {
		if (this.enabled != enabled) {
            if (!enabled) {
                // If this component has the focus, clear it
                if (isFocused()) {
                    clearFocus();
                }

                // Ensure that the mouse out event is processed
                if (isMouseOver()) {
                    mouseOut();
                }
            }

            this.enabled = enabled;

            componentStateListeners.enabledChanged(this);
        }
	}
	
	/**
	 * 组件是否阻塞。当任何一个祖先不可用时组件时阻塞的
	 * @return
	 */
	public function isBlocked():Bool {
		var blocked:Bool = false;

        var component:Component = this;

        while (component != null
            && !blocked) {
            blocked = !component.isEnabled();
            component = component.getParent();
        }

        return blocked;
	}
	
	/**
	 * 鼠标是位于组件
	 * @return
	 */
	public function isMouseOver():Bool {
        return (mouseLocation != null);
    }
	
	/**
	 * 返回组件的鼠标位置
	 * @return
	 */
	public function getMouseLocation():Point {
		return mouseLocation;
	}
	
	/**
	 * 返回组件的光标
	 * @return
	 */
	public function getCursor():Cursor {
        return cursor;
    }
	
	/**
	 * 设置光标
	 * @param	cursor
	 */
	public function setCursor(cursor:Cursor):Void {
		var previousCursor:Cursor = this.cursor;

        if (previousCursor != cursor) {
            this.cursor = cursor;

            if (isMouseOver()) {
				Mouse.setCursor(cursor);
            }

            componentListeners.cursorChanged(this, previousCursor);
        }
	}
	
	/**
	 * 返回组件的提示工具文字
	 * @return
	 */
	public function getTooltipText():String {
		return tooltipText;
	}
	
	/**
	 * 返回组件的提示工具延迟
	 * @return
	 */
	public function getTooltipDelay():Int {
		return tooltipDelay;
	}
	
	/**
	 * 设置提示工具的延迟
	 * @param	tooltipDelay
	 */
	public function setTooltipDelay(tooltipDelay:Int):Void {
		var previousTooltipDelay:Int = this.tooltipDelay;

        if (previousTooltipDelay != tooltipDelay) {
            this.tooltipDelay = tooltipDelay;
            componentListeners.tooltipDelayChanged(this, previousTooltipDelay);
        }
	}
	
	/**
	 * 设置组件的提示文字
	 * @param	tooltipText
	 */
	public function setTooltipText(tooltipText:String):Void {
		var previousTooltipText:String = this.tooltipText;

        if (previousTooltipText != tooltipText) {
            this.tooltipText = tooltipText;
            componentListeners.tooltipTextChanged(this, previousTooltipText);
        }
	}
	
	/**
	 * 组件是否完完全不透明
	 * @return
	 */
	public function isOpaque():Bool {
		return skin.isOpaque();
	}
	
	/**
	 * 组件是否可接受焦点
	 * @return
	 */
	public function isFocusable():Bool {
		var focusable:Bool = skin.isFocusable();

        if (focusable) {
            var component:Component = this;

            while (focusable
                && component != null
                && !(Std.is(component, Window))) {
                focusable = component.isVisible()
                    && isEnabled();

                component = component.getParent();
                focusable = (focusable && (component != null));
            }

            if (focusable) {
                var window:Window = untyped component;
                if (window != null) {
                    focusable = window.isVisible()
                            && window.isEnabled()
                            && window.isOpen()
                            && !window.isClosing();
                }
                else {
                    focusable = false;
                }
            }
        }

        return focusable;
	}
	
	/**
	 * 组件是否得到焦点
	 * @return
	 */
	public function isFocused():Bool {
        return (focusedComponent == this);
    }
	
	/**
	 * 设置组件焦点
	 * @param	focused
	 * @param	obverseComponent
	 */
	public function setFocused(focused:Bool, obverseComponent:Component):Void {
		if (focused) {
            cparent.descendantGainedFocus(this, obverseComponent);
        } else {
            cparent.descendantLostFocus(this);
        }

        componentStateListeners.focusedChanged(this, obverseComponent);
	}
	
	/**
	 * 请求焦点
	 * @return
	 */
	public function requestFocus():Bool {
		if (stage != null) {
			stage.focus = this;
			return true;
		}
		return false;
	}
	
	/**
	 * 清除焦点
	 */
	public static function clearFocus():Void {
		
	}
	
	/**
	 * 从绑定上下文中复制绑定的值到组件中，此功能须由子类提供。
	 * @param	context
	 */
	public function load(context:Dynamic):Void {
		
	}
	
	/**
	 * 从绑定上下文中复制绑定的值到组件中，此功能须由子类提供。
	 * @param	context
	 */
	public function store(context:Dynamic):Void {
		
	}
	
	/**
	 * 清楚所有绑定的值
	 */
	public function clear():Void {
		
	}
	
	/**
	 * 获取拖拽源
	 * @return
	 */
	public function getDragSource():IDragSource {
		return dragSource;
	}
	
	/**
	 * 设置拖拽源
	 * @param	dragSource
	 */
	public function setDragSource(dragSource:IDragSource):Void {
		var previousDragSource:IDragSource = this.dragSource;

        if (previousDragSource != dragSource) {
            this.dragSource = dragSource;
            componentListeners.dragSourceChanged(this, previousDragSource);
        }
	}
	
	/**
	 * 获取释放对象
	 */
	public function getDropTarget():IDropTarget {
        return cDropTarget;
    }

	/**
	 * 设置释放对象
	 * @param	dropTarget
	 */
    public function setDropTarget(dropTarget:IDropTarget):Void {
        var previousDropTarget:IDropTarget = this.cDropTarget;

        if (previousDropTarget != dropTarget) {
            this.cDropTarget = dropTarget;
            componentListeners.dropTargetChanged(this, previousDropTarget);
        }
    }
	
	/**
	 * 获取菜单处理器
	 */
	public function getMenuHandler():IMenuHandler {
        return menuHandler;
    }

	/**
	 * 设置菜单处理器
	 */
    public function setMenuHandler(menuHandler:IMenuHandler) {
        var previousMenuHandler:IMenuHandler = this.menuHandler;

        if (previousMenuHandler != menuHandler) {
            this.menuHandler = menuHandler;
            componentListeners.menuHandlerChanged(this, previousMenuHandler);
        }
    }
	
	/**
	 * 获取名字
	 * @return
	 */
	public function getName():String {
        return name;
    }

    /**
     * 设置名字
     * @param	String name
     */
    public function setName(name:String):Void {
        var previousName:String = this.name;

        if (previousName != name) {
            this.name = name;
            componentListeners.nameChanged(this, previousName);
        }
    }
	
	/**
	 * 获取组件的样式词典
	 * @return
	 */
	public function getStyles():Hash<Dynamic> {
		return styleDictionary;
	}
	
	/**
	 * 应用一组样式
	 * @param	styles
	 */
	public function setStyles(styles:Hash<Dynamic>):Void {
		if (styles == null) {
            throw new IllegalArgumentException("styles is null.");
        }

        for (key in styles.keys()) {
            getStyles().set(key, styles.get(key));
        }
	}
	
	/**
	 * 从字符串中应用一组样式
	 * @param	styles
	 */
	public function setStylesFromString(styles:String):Void {
		if (styles == null) {
			throw new IllegalArgumentException("styles is null.");
		}
		
		setStyles(Json.parse(styles));
	}
	
	/**
	 * 获取类型样式词典
	 * @return
	 */
	public static function getTypedStyles():ObjectHash < Class<Component>, Hash<Dynamic> > {
		return typedStyles;
	}
	
	/**
	 * 获取命名样式词典
	 * @return
	 */
	public static function getNamedStyles():Hash<Hash<Dynamic>> {
		return namedStyles;
	}
	
	/**
	 * 应用一组命名的样式
	 * @param	styleName
	 */
	public function setStyleName(styleName:String) {
		if (styleName == null) {
            throw new IllegalArgumentException();
        }

        var stylesLocal:Hash<Dynamic> = namedStyles.get(styleName);

        if (stylesLocal == null) {
            trace("Named style \"" + styleName + "\" does not exist.");
        } else {
            setStyles(stylesLocal);
        }
	}
	
	/**
	 * 应用一组命名的样式
	 * @param	styleNames
	 */
	public function setStyleNames(styleNames:Array<String>):Void {
        if (styleNames == null) {
            throw new IllegalArgumentException();
        }
		
        for (i in 0...styleNames.length) {
            setStyleName(styleNames[i]);
        }
    }
	
	/**
	 * 从字符串中应用一组命名的样式
	 * @param	styleNames
	 */
	public function setStyleNamesFromString(styleNames:String):Void {
        if (styleNames == null) {
            throw new IllegalArgumentException();
        }

        var styleNameArray:Array<String> = styleNames.split(",");
		
        for (i in 0...styleNames.length) {
            var styleName:String = styleNameArray[i];
            setStyleName(styleName.trim()); 
        } 
    }
	
	/**
	 * 获取用户数据
	 * @return
	 */
	public function getUserData():Hash<Dynamic> {
		return userDataDictionary;
	}
	
	/**
	 * 获取组件指定的属性。属性数据可以保存为任意类型，他们用来给父容器保存子组件的布局相关的元数据
	 * @param	key
	 * @return
	 */
	public function getAttribute(key:Dynamic):Dynamic {
		var attribute:Dynamic = null;
		
		if (attributes != null) {
			attribute = attributes.get(key);
		}
	}
	
	/**
	 * 设置组件指定的属性。属性数据可以保存为任意类型，他们用来给父容器保存子组件的布局相关的元数据
	 * @param	key
	 * @param	value
	 */
	public function setAttribute(key:String, value:Dynamic):Void {
		if (attributes == null) {
            attributes = new Hash<Dynamic>();
        }

        var previousValue:Dynamic;

        if (value != null) {
            previousValue = attributes.get(key);
        } else {
            previousValue = attributes.remove(key);
        }

        return previousValue;
	}
	
	/**
	 * 如果鼠标当前位于组件之上，令组件在当前鼠标位置触发mouseOut和mouseMove方法，
	 * 此方法主要用于共享容器的鼠标运动事件，因为他允许调用者根据事件消费逻辑重置鼠标状态
	 */
	public function reenterMouse():Void {
		
	}
	
	/**
	 * 
	 * @param	int xArgument
	 * @param	int yArgument
	 * @return
	 */
	public function mouseMove(xArgument:Float, yArgument:Float):Bool {
		var consumed:Bool = false;

        if (isEnabled()) {
            mouseLocation = new Point(xArgument, yArgument);

            if (triggerTooltipCallback != null) {
                triggerTooltipCallback.stop();
                triggerTooltipCallback = null;
            }

            triggerTooltipCallback = ApplicationContext.scheduleCallback(function(e:TimerEvent):Void{
                   var mouseLocationLocal:Point = getMouseLocation();
                   componentTooltipListeners.tooltipTriggered(this, mouseLocationLocal.x, mouseLocationLocal.y);
            }, tooltipDelay);

            consumed = componentMouseListeners.mouseMove(this, xArgument, yArgument);
        }

        return consumed;
	}
	
	/**
	 * 
	 */
	public function mouseOut():Void {
		if (isEnabled()) {
			mouseLocation = null;

            if (triggerTooltipCallback != null) {
                triggerTooltipCallback.stop();
                triggerTooltipCallback = null;
            }

            componentMouseListeners.mouseOut(this);
		}
	}
	
	/**
	 * 
	 * @param	button
	 * @param	xArgument
	 * @param	yArgument
	 * @return
	 */
	public function mouseDown(button:MouseButton, xArgument:Float, yArgument:Float):Bool {
		var consumed:Bool = false;

        if (isEnabled()) {
            if (triggerTooltipCallback != null) {
                triggerTooltipCallback.stop();
                triggerTooltipCallback = null;
            }

            consumed = componentMouseButtonListeners.mouseDown(this, button, xArgument, yArgument);
        }

        return consumed;
	}
	
	/**
	 * 
	 * @param	button
	 * @param	xArgument
	 * @param	yArgument
	 * @return
	 */
	public function mouseUp(button:MouseButton, xArgument:Float, yArgument:Float):Bool {
        var consumed:Bool = false;

        if (isEnabled()) {
            consumed = componentMouseButtonListeners.mouseUp(this, button, xArgument, yArgument);
        }

        return consumed;
    }
	
	/**
	 * 
	 * @param	button
	 * @param	xArgument
	 * @param	yArgument
	 * @param	count
	 * @return
	 */
	public function mouseClick(button:MouseButton, xArgument:Float, yArgument:Float, count:Int):Bool {
		var consumed:Bool = false;

        if (isEnabled()) {
            consumed = componentMouseButtonListeners.mouseClick(this, button, xArgument, yArgument, count);
        }

        return consumed;
	}
	
	/**
	 * 
	 * @param	scrollType
	 * @param	scrollAmount
	 * @param	wheelRotation
	 * @param	xArgument
	 * @param	yArgument
	 * @return
	 */
	public function mouseWheel(scrollType:MouseScrollType, scrollAmount:Int, wheelRotation:Int, xArgument:Int, yArgument:Int):Bool {
        var consumed:Bool = false;

        if (isEnabled()) {
            consumed = componentMouseWheelListeners.mouseWheel(this, scrollType,
                scrollAmount, wheelRotation, xArgument, yArgument);
        }

        return consumed;
    }
	
	/**
	 * 
	 * @param	keyCode
	 * @param	keyLocation
	 */
	public function keyPressed(keyCode:Int, keyLocation:KeyLocation) {
        var consumed:Bool = false;

        if (isEnabled()) {
            consumed = componentKeyListeners.keyPressed(this, keyCode, keyLocation);

            if (!consumed && cparent != null) {
                consumed = cparent.keyPressed(keyCode, keyLocation);
            }
        }

        return consumed;
    }
	
	/**
	 * 
	 * @param	keyCode
	 * @param	keyLocation
	 */
	public function keyReleased(keyCode:Int, keyLocation:KeyLocation) {
        var consumed:Bool = false;

        if (isEnabled()) {
            consumed = componentKeyListeners.keyReleased(this, keyCode, keyLocation);

            if (!consumed && cparent != null) {
                consumed = cparent.keyReleased(keyCode, keyLocation);
            }
        }

        return consumed;
    }
	
	override public function toString():String {
		var s:String = Util.getObjClsName(this);

        if (automationID != null) {
            s += "#" + automationID;
        }

        return s;
	}
	
	public function isEnabled():Bool {
		return enabled;
	}
	
	public function getComponentListeners():ListenerList<IComponentListener> {
		return componentListeners;
	}
	
	public function getComponentStateListeners():ListenerList<IComponentStateListener> {
		return componentStateListeners;
	}
	
	public function getComponentDecoratorListeners():ListenerList<IComponentDecoratorListener> {
		return componentDecoratorListeners;
	}
	
	public function getComponentStyleListeners():ListenerList<IComponentStyleListener> {
		return componentStyleListeners;
	}
	
	public function getComponentMouseListeners():ListenerList<IComponentMouseListener> {
		return componentMouseListeners;
	}
	
	public function getComponentMouseButtonListeners():ListenerList<IComponentMouseButtonListener> {
		return componentMouseButtonListeners;
	}
	
	public function getComponentMouseWheelListeners():ListenerList<IComponentMouseWheelListener> {
		return componentMouseWheelListeners;
	}
	
	public function getComponentKeyListeners():ListenerList<IComponentKeyListener> {
		return componentKeyListeners;
	}
	
	public function getComponentTooltipListeners():ListenerList<IComponentTooltipListener> {
		return componentTooltipListeners;
	}
	
	public function getComponentDataListeners():ListenerList<IComponentDataListener> {
		return componentDataListeners;
	}
	
	public function getComponentClassListeners():ListenerList<IComponentClassListener> {
		return componentClassListeners;
	}
	
}

class ComponentListenerList extends WTKListenerList<IComponentListener>, implements IComponentListener{
	/**
	 * 当父容器改变执行（组件被添加或删除）
	 * @param	c
	 * @param	prevParent
	 */
	public function parentChanged(c:Component, prevParent:Container):Void {
		for (l in this) {
			l.parentChanged(c, prevParent);
		}
	}
	
	/**
	 * 组件尺寸更改时候执行
	 * @param	c
	 * @param	prevWidth
	 * @param	prevHeight
	 */
	public function sizeChanged(c:Component, prevWidth:Float, prevHeight:Float):Void {
		for (l in this) {
			l.sizeChanged(c, prevWidth, prevHeight);
		}
	}
	
	/**
	 * 当组件期望尺寸更改时执行
	 * @param	c
	 * @param	prevPrefWid
	 * @param	prevPrefHei
	 */
	public function preferredSizeChanged(c:Component, prevPrefWid:Float, prevPrefHei:Float):Void {
		for (l in this) {
			l.preferredSizeChanged(c, prevPrefWid, prevPrefHei);
		}
	}
	
	/**
	 * 宽的极限更改时执行
	 * @param	c
	 * @param	prevMinWid
	 * @param	prevMaxWid
	 */
	public function widthLimitsChanged(c:Component, prevMinWid:Float, prevMaxWid:Float):Void {
		for (l in this) {
			l.widthLimitsChanged(c, prevMinWid, prevMaxWid);
		}
	}
	
	/**
	 * 高的极限更改时执行
	 * @param	c
	 * @param	prevMinHei
	 * @param	prevMaxHei
	 */
	public function heightLimitsChanged(c:Component, prevMinHei:Float, prevMaxHei:Float):Void {
		for (l in this) {
			l.heightLimitsChanged(c, prevMinHei, prevMaxHei);
		}
	}
	
	/**
	 * 当组件的位置更改时执行
	 * @param	c
	 * @param	prevX
	 * @param	prevY
	 */
	public function locationChanged(c:Component, prevX:Float, prevY:Float):Void {
		for (l in this) {
			l.locationChanged(c, prevX, prevY);
		}
	}
	
	/**
	 * 当组建的可见度更改时执行
	 * @param	c
	 */
	public function visibleChanged(c:Component):Void {
		for (l in this) {
			l.visibleChanged(c);
		}
	}
	
	/**
	 * 当组件的光标更改时调用
	 * @param	c
	 */
	public function cursorChanged(c:Component, cursor:Cursor):Void {
		for (l in this) {
			l.cursorChanged(c, cursor);
		}
	}
	
	/**
	 * 当组件的提示文字改变时调用
	 * @param	c
	 * @param	prevText
	 */
	public function tooltipTextChanged(c:Component, prevText:String):Void {
		for (l in this) {
			l.tooltipTextChanged(c, prevText);
		}
	}
	
	/**
	 * 当组件的提示延迟时间更改时时调用
	 * @param	c
	 * @param	prevDelay
	 */
	public function tooltipDelayChanged(c:Component, prevDelay:Int):Void {
		for (l in this) {
			l.tooltipDelayChanged(c, prevDelay);
		}
	}
	
	/**
	 * 当组件的拖拽源更改时执行
	 * @param	c
	 * @param	prevDragSource
	 */
	public function dragSourceChanged(c:Component, prevDragSource:IDragSource):Void {
		for (l in this) {
			l.dragSourceChanged(c, prevDragSource);
		}
	}
	
	/**
	 * 当组件的释放源更改时执行
	 * @param	c
	 * @param	prevDropTarget
	 */
	public function dropTargetChanged(c:Component, prevDropTarget:IDropTarget):Void {
		for (l in this) {
			l.dropTargetChanged(c, prevDropTarget);
		}
	}
	
	/**
	 * 当组件的上下文处理器更改时执行
	 * @param	c
	 * @param	prevMenuHandler
	 */
	public function menuHandlerChanged(c:Component, prevMenuHandler:IMenuHandler):Void {
		for (l in this) {
			l.menuHandlerChanged(c, prevMenuHandler);
		}
	}
	
	/**
	 * 当组件的名字更改时执行
	 * @param	c
	 * @param	prevMenuHandler
	 */
	public function nameChanged(c:Component, previousName:String):Void {
		for (l in this) {
			l.nameChanged(c, previousName);
		}
	}
}

class ComponentStateListenerList extends WTKListenerList<IComponentStateListener>, implements IComponentStateListener{
	/**
	 * 当组件的可用状态改变时调用
	 * @param	c
	 */
	public function enabledChanged(c:Component):Void {
		for (l in this) {
			l.enabledChanged(c);
		}
	}
	
	/**
	 * 当组件的焦点状态时调用
	 * @param	c
	 * @param	obverseComponent
	 */
	public function focusedChanged(c:Component, obverseComponent:Component):Void {
		for (l in this) {
			l.focusedChanged(c, obverseComponent);
		}
	}
}

class ComponentDecoratorListenerList extends WTKListenerList<IComponentDecoratorListener>, implements IComponentDecoratorListener {
	/**
	 * 当组件的装饰器被插入时调用
	 * @param	c
	 * @param	index
	 */
	public function decoratorInserted(c:Component, index:Int):Void {
		for (l in this) {
			l.decoratorInserted(c, index);
		}
	}
	
	/**
	 * 当组件在装饰器队列的装饰器被更新时执行
	 * @param	c
	 * @param	index
	 * @param	prevDecorator
	 */
	public function decoratorUpdated(c:Component, index:Int, prevDecorator:IDecorator):Void {
		for (l in this) {
			l.decoratorUpdated(c, index, prevDecorator);
		}
	}
	
	/**
	 * 当组件在装饰器队列的装饰器被删除时执行
	 * @param	c
	 * @param	index
	 * @param	decorators
	 */
	public function decoratorsRemoved(c:Component, index:Int, decorators:Array<IDecorator>):Void {
		for (l in this) {
			l.decoratorsRemoved(c, index, decorators);
		}
	}
}

class ComponentStyleListenerList extends WTKListenerList<IComponentStyleListener>, implements IComponentStyleListener {
	/**
	 * 当组件的样式被更新时调用
	 * @param	c
	 * @param	stylekey
	 * @param	prevValue
	 */
	public function styleUpdated(c:Component, stylekey:String, prevValue:Dynamic):Void {
		for (l in this) {
			l.styleUpdated(c, stylekey, prevValue);
		}
	}
}

class ComponentMouseListenerList extends WTKListenerList<IComponentMouseListener>, implements IComponentMouseListener {
	/**
	 * 当鼠标在组件上移动时调用
	 * @param	c
	 * @param	x
	 * @param	y
	 * @return
	 */
	public function mouseMove(c:Component, x:Float, y:Float):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.mouseMove(c, x, y) || res;
		}
		return res;
	}
	
	/**
	 * 当组件经过组建时
	 * @param	c
	 */
	public function mouseOver(c:Component):Void {
		for (l in this) {
			l.mouseOver(c);
		}
	}
	
	/**
	 * 当鼠标移出组件时
	 * @param	c
	 */
	public function mouseOut(c:Component):Void {
		for (l in this) {
			l.mouseOut(c);
		}
	}
}

class ComponentMouseButtonListenerList extends WTKListenerList<IComponentMouseButtonListener>, implements IComponentMouseButtonListener {
	/**
	 * 当鼠标在组件上按下时调用
	 * @param	c
	 * @param	button
	 * @param	x
	 * @param	y
	 * @return
	 */
	public function mouseDown(c:Component, button:MouseButton, x:Float, y:Float):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.mouseDown(c, button, x, y) || res;
		}
		return res;
	}
	
	/**
	 * 当鼠标在组件上释放时调用
	 * @param	c
	 * @param	button
	 * @param	x
	 * @param	y
	 * @return
	 */
	public function mouseUp(c:Component, button:MouseButton, x:Float, y:Float):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.mouseUp(c, button, x, y) || res;
		}
		return res;
	}
	
	/**
	 * 当鼠标在组件上点击时调用
	 * @param	c
	 * @param	button
	 * @param	x
	 * @param	y
	 * @param	count
	 * @return
	 */
	public function mouseClick(c:Component, button:MouseButton, x:Float, y:Float, count:Int):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.mouseClick(c, button, x, y, count) || res;
		}
		return res;
	}
}

class ComponentMouseWheelListenerList extends WTKListenerList<IComponentMouseWheelListener>, implements IComponentMouseWheelListener {
	/**
	 * 当鼠标滑轮在组件上滚动时执行
	 * @param	c
	 * @param	scrollType
	 * @param	scrollAmount
	 * @param	wheelRotation
	 * @param	x
	 * @param	yy
	 */
	public function mouseWheel(c:Component, scrollType:MouseScrollType, scrollAmount:Int, wheelRotation:Int, x:Float, y:Float):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.mouseWheel(c, scrollType, scrollAmount, wheelRotation, x, y) || res;
		}
		return res;
	}
}

class ComponentKeyListenerList extends WTKListenerList<IComponentKeyListener>, implements IComponentKeyListener {
	/**
	 * 当按键按完时调用
	 * @param	c
	 * @param	character
	 */
	public function keyTyped(c:Component, character:String):Void {
		for (l in this) {
			l.keyTyped(c, character);
		}
	}
	
	/**
	 * 当按键被按下时调用
	 * @param	c
	 * @param	character
	 */
	public function keyPressed(c:Component, keyCode:Int, keyLocation:KeyLocation):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.keyPressed(c, keyCode, keyLocation) || res;
		}
		return res;
	}
	
	/**
	 * 当按键被释放时调用
	 * @param	c
	 * @param	character
	 */
	public function keyReleased(c:Component, keyCode:Int, keyLocation:KeyLocation):Bool {
		var res:Bool = false;
		for (l in this) {
			res = l.keyPressed(c, keyCode, keyLocation) || res;
		}
		return res;
	}
}

class ComponentTooltipListenerList extends WTKListenerList<IComponentTooltipListener>, implements IComponentTooltipListener {
	/**
	 * 当提示被组件触发时啊用
	 * @param	c
	 * @param	x
	 * @param	y
	 */
	public function tooltipTriggered(c:Component, x:Float, y:Float):Void {
		for (l in this) {
			l.tooltipTriggered(c, x, y);
		}
	}
}

class ComponentDataListenerList extends WTKListenerList<IComponentDataListener>, implements IComponentDataListener {
	/**
	 * 当值被添加到组件的用户数据字典中时
	 * @param	c
	 * @param	key
	 */
	public function valueAdded(c:Component, key:String):Void {
		for (l in this) {
			l.valueAdded(c, key);
		}
	}
	
	/**
	 * 当组件用户数据的值被更新时
	 * @param	c
	 * @param	key
	 * @param	prevValue
	 */
	public function valueUpdated(c:Component, key:String, prevValue:Dynamic):Void {
		for (l in this) {
			l.valueUpdated(c, key, prevValue);
		}
	}
	
	/**
	 * 当组件用户数据词典中的值被删除
	 * @param	c
	 * @param	key
	 * @param	value
	 */
	public function valueRemoved(c:Component, key:String, value:Dynamic):Void {
		for (l in this) {
			l.valueRemoved(c, key, value);
		}
	}
}

class ComponentClassListenerList extends WTKListenerList<IComponentClassListener>, implements IComponentClassListener {
	/**
	 * 当焦点组件被更改时
	 * @param	c
	 */
	public function focusedComponentChanged(c:Component):Void {
		for (l in this) {
			l.focusedComponentChanged(c);
		}
	}
}